Merged
Conversation
added 5 commits
April 20, 2026 07:53
…value flags Commander's default behavior is to accept the next argv token as the value of a required-value option, even if that token looks like another flag or a subcommand name. This made commands like `switchbot --profile devices list` or `switchbot events mqtt-tail --max --help` silently swallow `devices`/`--help` and then fail confusingly downstream. Introduce a small set of argParser factories (intArg, durationArg, stringArg, enumArg) in src/utils/arg-parsers.ts that fail fast with a clear InvalidArgumentError during parse: - intArg rejects anything not a valid integer (incl. `-`-prefixed tokens) - durationArg requires a parseable duration string - stringArg rejects `--`-prefixed values and, when `disallow` is set, any known top-level subcommand name (fixes `--profile devices list`) - enumArg restricts values to a fixed set Wire these into global flags in src/index.ts and into `events mqtt-tail --max`, `events tail --port/--max`, and `devices watch --interval/--max`. Also propagate `exitOverride` to every registered subcommand so subcommand argParser errors map to exit code 2 (previously produced exit 1 because the root override wasn't inherited), and also add a fallback CommanderError catch around `parseAsync` for errors that skip the handler entirely. Includes a regression test for the `events mqtt-tail --max --help` case and new coverage for the argParser factories.
…evices - `switchbot devices ls` now resolves to `devices list` (common shorthand). - When a user runs `devices command <id> <cmd>` against a deviceId that isn't in the local cache, print a one-line hint to stderr suggesting they run `devices list` first so command validation can kick in. Non-blocking: the request still goes through.
Patch release covering: - Token-swallowing fix on required-value flags (--profile, --timeout, --max, …). - `devices ls` alias + soft hint when commanding an uncached device. - Correct exit code (2) on subcommand argParser errors. README gets a short tip explaining the `--flag=value` escape hatch for when a user really does want a value that looks like another flag.
Extends the argParser factories from commit d133354 to every remaining required-value option across the command surface so no flag can silently swallow the next argv token: - batch: --filter / --ids / --concurrency / --type / --idempotency-key-prefix - cache: --key as enumArg - catalog: --source as enumArg - config: --name / --profile-name / --token / --secret - device-meta, expand, history, mcp, schema, webhook: all string/int/enum options now use the corresponding factory - events (sinks): --path / --filter / --topic + every --*-url / --*-token / --*-chat / --*-webhook-id / --*-event-type - watch: remaining string options Tests updated where the argParser-formatted error message replaces the previous hand-rolled UsageError text. Net behavior is unchanged on the happy path; invalid values now fail earlier (parse phase) with a consistent "option '--X <Y>' argument 'Z' is invalid" prefix.
The previous completion scripts only enumerated `config / devices / scenes / webhook / completion` and a tiny subset of global flags — anything typed at `switchbot <Tab>` for `mcp`, `events`, `quota`, `catalog`, `cache`, `doctor`, `schema`, `history`, `plan`, or `capabilities` produced no suggestions. Update all four shell scripts (bash / zsh / fish / powershell) to enumerate: - every top-level subcommand - every subcommand of `events`, `quota`, `catalog`, `cache`, `history`, `plan` - the new `ls` alias for `devices` - every global flag introduced since v2.0 (`--format`, `--fields`, `--retry-on-429`, `--backoff`, `--no-retry`, `--no-quota`, `--cache`, `--no-cache`, `--profile`, `--audit-log`, `--audit-log-path`) Tests assert the generated scripts contain the new command names and flags.
chenliuyun
pushed a commit
that referenced
this pull request
Apr 20, 2026
C1 (#14): update --idempotency-key / --idempotency-key-prefix help text in devices.ts and batch.ts to mention process-local scope, per-process cache semantics, and that independent CLI invocations do not share cache. C2 (#15): mcp --help "eight tools" → "eleven tools"; list all 11 by name including get_device_history, query_device_history, aggregate_device_history. C3 (#17): add `scenes describe <sceneId>` subcommand. Returns sceneId, sceneName, stepCount:null, and a note explaining v1.1 API limitation. Exits 2 with scene_not_found + candidate list on unknown sceneId. Adds 'scenes describe' to COMMAND_META in capabilities.ts. Adds 2 tests (known + unknown scene). C4 (#13): add JSDoc comment on hints field in agent-bootstrap.ts clarifying empty array semantics. Add 'hints' field to cliAddedFields in schema.ts. C5 (#16): create docs/verbose-redaction.md documenting masked headers (authorization, token, sign, nonce, x-api-key, cookie, set-cookie, x-auth-token, t) and the --trace-unsafe opt-out flag. C6 (#18): plan schema output now includes agentNotes.deviceNameStrategy documenting that deviceName uses require-unique resolution and plans should pin deviceId for determinism. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
chenliuyun
pushed a commit
that referenced
this pull request
Apr 20, 2026
Document every fix landed in this branch beyond the history-aggregate feature: bugs #1, #4, #5, #6, #8, #9, #10, #11, #12, #13, #14, #15, #16, #17, #18 from the OpenClaw v2.4.0 smoke-test report. Call out the deferred items (#2, #7) explicitly so readers don't assume they were overlooked. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4 tasks
chenliuyun
pushed a commit
that referenced
this pull request
Apr 20, 2026
C1 (#14): update --idempotency-key / --idempotency-key-prefix help text in devices.ts and batch.ts to mention process-local scope, per-process cache semantics, and that independent CLI invocations do not share cache. C2 (#15): mcp --help "eight tools" → "eleven tools"; list all 11 by name including get_device_history, query_device_history, aggregate_device_history. C3 (#17): add `scenes describe <sceneId>` subcommand. Returns sceneId, sceneName, stepCount:null, and a note explaining v1.1 API limitation. Exits 2 with scene_not_found + candidate list on unknown sceneId. Adds 'scenes describe' to COMMAND_META in capabilities.ts. Adds 2 tests (known + unknown scene). C4 (#13): add JSDoc comment on hints field in agent-bootstrap.ts clarifying empty array semantics. Add 'hints' field to cliAddedFields in schema.ts. C5 (#16): create docs/verbose-redaction.md documenting masked headers (authorization, token, sign, nonce, x-api-key, cookie, set-cookie, x-auth-token, t) and the --trace-unsafe opt-out flag. C6 (#18): plan schema output now includes agentNotes.deviceNameStrategy documenting that deviceName uses require-unique resolution and plans should pin deviceId for determinism.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Patch release 2.2.1 fixing three token-swallowing UX bugs reported against 2.2.0, plus
lsalias and soft hint for uncached device IDs. Also extends the argParser hardening pattern to every remaining string/int/enum option across the CLI, and updates shell completion scripts to cover all 15 subcommands and new global flags.Bugs fixed (from 2.2.0 regression report)
switchbot --profile devices listno longer swallowsdevicesas the profile value. Now exits 2 with--profile requires a value but got "devices", which is a subcommand name.switchbot --timeout devices list(missing value) now exits 2 with--timeout requires a numeric value, got "devices".switchbot events mqtt-tail --max --helpnow exits 2 instead of silently hanging; subcommand argParser errors now correctly surface as exit 2 via recursiveexitOverride.New UX
switchbot devices ls— short alias fordevices list.switchbot devices command <id> ...prints a one-line soft hint to stderr when the device ID isn't in the local cache (non-blocking).state='failed'(e.g. AWS IoT credential expiry) now triggersprocess.exit(1)instead of the confusing Node "Unsettled Top-Level Await" message.Commits
d133354fix(cli): harden arg parsing to prevent token-swallowing on required-value flags62910d9feat(devices): add 'ls' alias for 'list' and soft hint for uncached devicesa4f8cdcchore(release): bump to 2.2.1 and document UX parser hardening4aeb057fix(cli): extend arg-parser hardening to remaining commands10cb99bfix(completion): cover all subcommands and new global flagsTest plan
npm run build— clean TS compilenpm test— 720/720 tests passing (added 14 arg-parser factory tests + regression cases for each B.1/B.2/B.3 bug +lsalias + soft hint on/off)switchbot --profile devices list→ exit 2, "subcommand name" hintswitchbot --timeout devices list→ exit 2, "must be an integer"switchbot events mqtt-tail --max --help→ exit 2, "requires a numeric value"switchbot --profile=home devices list --help→ exit 0 (still works)switchbot devices ls --help→ exit 0, showslist|lsCompatibility
No breaking changes. No new public API, no new subcommands, no new dependencies. Semver patch.